#pragma once

#include <string>
#include <unordered_map>
#include <iostream>
#include "Connection.hpp"

#include "Log.hpp"
#include "Epoller.hpp"
using namespace EpollerModule;

#define EPPLL_BLOCK -1
// 该模块负责对

static int defaultfd = -1;
static const int gmaxevents = 128;
static const int defautimeout = EPPLL_BLOCK; // 阻塞
class TcpServer
{
public:
    TcpServer()
        : _isrunning(false), _timeout(defautimeout)
    {
        _epoller.InitEpoller();
    }
    bool IsConnectionExists(int sockfd)
    {
        auto iter = _connections.find(sockfd);
        if (iter == _connections.end())
            return false;
        return true;
    }
    void AddConnection(Connection *conn)
    {
        if (!conn)
            return;
        if (IsConnectionExists(conn->GetConnFd()))
            return;

        // 1.添加事件到map中
        _connections.insert(std::make_pair(conn->GetConnFd(), conn));
        lg.LogMessage(Info, "Add a new connection success!,fd %d", conn->GetConnFd());
        // 2.添加事件到epoll
        _epoller.AddEvent(conn->GetConnFd(), conn->Event());
    }

    void RemoveConnection(int sockfd)
    {
        if(!IsConnectionExists(sockfd))
        {
            lg.LogMessage(Warning,"remove error");
            return ;
        }
        
        _epoller.DelEvent(sockfd);

        _connections.erase(sockfd);
    }
    void EventEnable(int sockfd, bool reader, bool sender)
    {
        if(!IsConnectionExists(sockfd))
            return ;
        uint32_t event = (reader ? EPOLLIN : 0) | (sender ? EPOLLOUT : 0) | EPOLLET;
        //1.修改关心事件
        _connections[sockfd]->SetEvent(event);
        //2.写透到epoll内核
        _epoller.ModEvent(sockfd,event);

    }
    void LoopOnce(int timeout)
    {
        // 1.等待
        int n = _epoller.wait(_revs, gmaxevents, timeout);
        // if(n<0) 异常统一处理
        for (int i = 0; i < n; i++)
        {
            int sockfd = _revs[i].data.fd;
            uint32_t event = _revs[i].events;

            // 统一处理异常
            if (event & EPOLLERR)
                event |= (EPOLLIN | EPOLLOUT);
            if (event & EPOLLRDHUP)
                event |= (EPOLLIN | EPOLLOUT);

            // 注意sockfd必须没有被关闭
            if ((event & EPOLLIN) && IsConnectionExists(sockfd))
            {
                // 注意回调方法不能为空，才能调用
                if (_connections[sockfd]->_recver)
                    _connections[sockfd]->_recver(_connections[sockfd]);
            }

            if ((event & EPOLLOUT) && IsConnectionExists(sockfd))
            {
                if (_connections[sockfd]->_sender)
                    _connections[sockfd]->_sender(_connections[sockfd]);
            }
        }
    }

    void Dispatcher()
    {
        _isrunning = true;
        while (_isrunning)
        {
            _epoller.DebugList();
            LoopOnce(_timeout);
            sleep(1);
        }
        _isrunning = false;
    }

    ~TcpServer()
    {
    }

private:
    Epoller _epoller;

    std::unordered_map<int, Connection *> _connections;
    bool _isrunning;

    int _timeout;
    struct epoll_event _revs[gmaxevents];
};
